package cz.vutbr.fit.xzemko01.tfmcbs.validation.validators;

import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;

import cz.vutbr.fit.xzemko01.tfmcbs.model.Delegate;
import cz.vutbr.fit.xzemko01.tfmcbs.model.Entity;
import cz.vutbr.fit.xzemko01.tfmcbs.model.Interface;
import cz.vutbr.fit.xzemko01.tfmcbs.model.Realization;
import cz.vutbr.fit.xzemko01.tfmcbs.model.RequiringPort;
import cz.vutbr.fit.xzemko01.tfmcbs.validation.utils.DiagnosticBuilder;

public final class InterfaceValidator implements Validator<Interface> {
	
	private static InterfaceValidator interfaceValidator;
	
	private Validator<Entity> entityValidator;
	
	private InterfaceValidator() {
		entityValidator = EntityValidator.getInstance();
	}
	
	public static Validator<Interface> getInstance() {
		if(interfaceValidator == null) {
			interfaceValidator = new InterfaceValidator();
		}
		return interfaceValidator;
	}
	
	@Override
	public boolean validate(Interface _interface, DiagnosticChain diagnostics, Map<Object, Object> context) {
		boolean result = entityValidator.validate(_interface, diagnostics, context);
		result &= validateInterfaceRealized(_interface, diagnostics, context);
		return result;		
	}
	
	private boolean validateInterfaceRealized(Interface _interface, DiagnosticChain diagnostics, Map<Object, Object> context) {
		List<Realization> realizationList = _interface.getRealizations(); 
		if((realizationList == null || realizationList.isEmpty()) 
				&& !isInterfaceDelegatedByRequiringPort(_interface)) 
		{
			Diagnostic diagnostic = new DiagnosticBuilder(_interface)
				.setMessage("Interface \"" + _interface.getName() + "\" is not realized.")
				.setSeverity(Diagnostic.WARNING).build();
			diagnostics.add(diagnostic);
			return false;
		}
		return true;
	}
	
	private boolean isInterfaceDelegatedByRequiringPort(Interface _interface) {
		List<Delegate> delegateList = _interface.getDelegates();
		if(delegateList == null || delegateList.isEmpty()) {
			return false;
		}
		
		for(Delegate delegate : delegateList) {
			if(delegate.getPort() instanceof RequiringPort) {
				return true;
			}
		}
		
		return false;
	}
}
